[XEND] Fix PCI configuration parsing and SXP output
authorAlastair Tse <atse@xensource.com>
Thu, 16 Nov 2006 13:49:05 +0000 (13:49 +0000)
committerAlastair Tse <atse@xensource.com>
Thu, 16 Nov 2006 13:49:05 +0000 (13:49 +0000)
PCI configuration is formatted differently from other device
configurations because of the requirement that all pci devices need to
be present when it is initialised.

Signed-off-by: Alastair Tse <atse@xensource.com>
tools/python/xen/xend/XendConfig.py
tools/python/xen/xend/server/pciif.py

index 93ad4b6598c698493f460f5e0e1a2f220021e05f..2d86122428f7c17ef8f0648c1ea64f2416ded770 100644 (file)
@@ -17,6 +17,7 @@
 
 import re
 import time
+import types
 
 from xen.xend import sxp
 from xen.xend import uuid
@@ -450,11 +451,36 @@ class XendConfig(dict):
         for c in sxp.children(parsed, 'backend'):
             cfg['backend'].append(sxp.name(sxp.child0(c)))
 
+        # Parsing the device SXP's. In most cases, the SXP looks
+        # like this:
+        #
+        # [device, [vif, [mac, xx:xx:xx:xx:xx:xx], [ip 1.3.4.5]]]
+        #
+        # However, for PCI devices it looks like this:
+        #
+        # [device, [pci, [dev, [domain, 0], [bus, 0], [slot, 1]]]]
+        #
+        # It seems the reasoning for this difference is because
+        # pciif.py needs all the PCI device configurations at
+        # the same time when creating the devices.
+        #
+        # To further complicate matters, Xen 2.0 configuration format
+        # uses the following for pci device configuration:
+        #
+        # [device, [pci, [domain, 0], [bus, 0], [dev, 1], [func, 2]]]
+        #
+        # Hence we deal with pci device configurations outside of
+        # the regular device parsing.
+        
         cfg['device'] = {}
         for dev in sxp.children(parsed, 'device'):
             config = sxp.child0(dev)
             dev_type = sxp.name(config)
             dev_info = {}
+            
+            if dev_type == 'pci':
+                continue 
+            
             for opt, val in config[1:]:
                 dev_info[opt] = val
             log.debug("XendConfig: reading device: %s" % dev_info)
@@ -462,9 +488,34 @@ class XendConfig(dict):
             dev_uuid = dev_info.get('uuid', uuid.createString())
             dev_info['uuid'] = dev_uuid
             cfg['device'][dev_uuid] = (dev_type, dev_info)
-            
-            #cfg['device'].append((sxp.name(config), config))
 
+        # deal with PCI device configurations if they exist
+        for dev in sxp.children(parsed, 'device'):
+            config = sxp.child0(dev)
+            dev_type = sxp.name(config)
+
+            if dev_type != 'pci':
+                continue
+            
+            dev_attr = sxp.child_value(config, 'dev')
+            if isinstance(dev_attr, (types.ListType, types.TupleType)):
+                for pci_dev in sxp.children(config, 'dev'):
+                    dev_info = {}
+                    for opt, val in pci_dev[1:]:
+                        dev_info[opt] = val
+                    log.debug("XendConfig: reading device: %s" % dev_info)
+                    dev_uuid = dev_info.get('uuid', uuid.createString())
+                    dev_info['uuid'] = dev_uuid
+                    cfg['device'][dev_uuid] = (dev_type, dev_info)
+                    
+            else: # Xen 2.0 PCI device configuration
+                for opt, val in config[1:]:
+                    dev_info[opt] = val
+                log.debug("XendConfig: reading device: %s" % dev_info)
+                # create uuid if it doesn't
+                dev_uuid = dev_info.get('uuid', uuid.createString())
+                dev_info['uuid'] = dev_uuid
+                cfg['device'][dev_uuid] = (dev_type, dev_info)
 
         # Extract missing data from configuration entries
         if 'image' in cfg:
@@ -859,10 +910,27 @@ class XendConfig(dict):
         return sxpr
 
     def all_devices_sxpr(self):
+        """Returns the SXPR for all devices in the current configuration."""
         sxprs = []
+        pci_devs = []
         for dev_type, dev_info in self['device'].values():
-            sxpr =  self.device_sxpr(dev_type = dev_type, dev_info = dev_info)
-            sxprs.append((dev_type, sxpr))
+            if dev_type == 'pci': # special case for pci devices
+                pci_devs.append(dev_info)
+            else:
+                sxpr =  self.device_sxpr(dev_type = dev_type,
+                                         dev_info = dev_info)
+                sxprs.append((dev_type, sxpr))
+
+        # if we have any pci_devs, we parse them differently into
+        # one single pci SXP entry.
+        if pci_devs:
+            sxpr = ['pci',]
+            for dev_info in pci_devs:
+                dev_sxpr = self.device_sxpr(dev_type = 'dev',
+                                            dev_info = dev_info)
+                sxpr.append(dev_sxpr)
+            sxprs.append(('pci', sxpr))
+            
         return sxprs
 
                      
index aa7f3c8c98f64fc602cd1391e693adaff7d22e41..eaab90529ff873b703b1dcb2789e7893fab6d692 100644 (file)
@@ -65,7 +65,7 @@ class PciController(DevController):
                     else:
                         return default
 
-                if isinstance(val, types.StringType):
+                if isinstance(val, types.StringTypes):
                     return int(val, 16)
                 else:
                     return val
@@ -79,7 +79,7 @@ class PciController(DevController):
         back = {}
 
         val = sxp.child_value(config, 'dev')
-        if isinstance(val, list):
+        if isinstance(val, (types.ListType, types.TupleType)):
             pcidevid = 0
             for dev_config in sxp.children(config, 'dev'):
                 domain = get_param(dev_config, 'domain', 0)
@@ -89,7 +89,7 @@ class PciController(DevController):
 
                 self.setupDevice(domain, bus, slot, func)
 
-                back['dev-%i'%(pcidevid)]="%04x:%02x:%02x.%02x"% \
+                back['dev-%i' % pcidevid]="%04x:%02x:%02x.%02x"% \
                         (domain, bus, slot, func)
                 pcidevid+=1
             
@@ -115,19 +115,19 @@ class PciController(DevController):
         pci_devs = []
         
         for i in range(int(num_devs)):
-            (dev_config,) = self.readBackend(devid, 'dev-%d'%(i))
+            dev_config = self.readBackend(devid, 'dev-%d' % i)
 
-            pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \
-                    r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \
-                    r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \
-                    r"(?P<func>[0-9a-fA-F]{1,2})", dev_config)
+            pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" +
+                                 r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + 
+                                 r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + 
+                                 r"(?P<func>[0-9a-fA-F]{1,2})", dev_config)
             
             if pci_match!=None:
-                pci_dev_info = pci_match.groupdict('0')
+                pci_dev_info = pci_match.groupdict()
                 pci_devs.append({'domain': '0x%(domain)s' % pci_dev_info,
                                  'bus': '0x%(bus)s' % pci_dev_info,
-                                 'slot': '0x(slot)s' % pci_dev_info,
-                                 'func': '0x(func)s' % pci_dev_info})
+                                 'slot': '0x%(slot)s' % pci_dev_info,
+                                 'func': '0x%(func)s' % pci_dev_info})
 
         result['dev'] = pci_devs
         return result